import { Middleware, MiddlewareContext, HttpResponse } from '../../core/types';

interface CacheEntry {
  response: HttpResponse;
  timestamp: number;
}

const memoryCache = new Map<string, CacheEntry>();

export interface CacheOptions {
  getKey?: (ctx: MiddlewareContext) => string;
  get?: (key: string) => CacheEntry | undefined;
  set?: (key: string, value: CacheEntry) => void;
  shouldCache?: (ctx: MiddlewareContext) => boolean;
  maxAge?: number;
}

export function cache(options: CacheOptions = {}): Middleware {
  const {
    getKey = (ctx) => `${ctx.config.method}:${ctx.config.url}`,
    get = (key) => memoryCache.get(key),
    set = (key, value) => memoryCache.set(key, value),
    shouldCache = (ctx) => ctx.config.method === 'GET',
    maxAge = 5 * 60 * 1000,
  } = options;

  return async (ctx: MiddlewareContext, next) => {
    if (!shouldCache(ctx)) {
      return next();
    }

    const key = getKey(ctx);
    const cached = get(key);

    if (cached && Date.now() - cached.timestamp < maxAge) {
      ctx.response = cached.response;
      return;
    }

    await next();

    if (ctx.response && !ctx.error) {
      set(key, {
        response: ctx.response,
        timestamp: Date.now(),
      });
    }
  };
}
